#include "Graph.h"


//Graph Node
GraphNode::GraphNode()
{
	m_Pos=D3DXVECTOR2(0,0);
	m_Index=-1;
	m_Active=false;
}
GraphNode::GraphNode(D3DXVECTOR2 p, int i)
{
	m_Pos = p;
	m_Index=i;
	m_Active=true;
}

GraphNode::GraphNode(D3DXVECTOR2 p)
{
	m_Pos = p;
	m_Index=-1;
	m_Active=false;
}

void GraphNode::SetPos(D3DXVECTOR2 p)
{
	m_Pos=p;
}
void GraphNode::SetIndex(int i)
{
	m_Index=i;
}
void GraphNode::Activate()
{
	m_Active=true;
}
void GraphNode::Deactivate()
{
	m_Active=false;
}

D3DXVECTOR2 GraphNode::GetPos() const
{
	return m_Pos;
}
int GraphNode::GetIndex() const
{
	return m_Index;
}
bool GraphNode::GetActive()
{
	return m_Active;
}


//Graph Edge

GraphEdge::GraphEdge()
{
}

GraphEdge::GraphEdge(int f, int t)
{
	m_From=f;
	m_To=t;
	m_Cost=1;
}
GraphEdge::GraphEdge(int f, int t, float c)
{
	m_From=f;
	m_To=t;
	m_Cost=c;
}

int GraphEdge::GetFrom()
{
	return m_From;
}
int GraphEdge::GetTo()
{
	return m_To;
}
float GraphEdge::GetCost()
{
	return m_Cost;
}
void GraphEdge::SetCost(float c)
{
	m_Cost=c;
}

//Graph

Graph::Graph()
{
	m_NextIndex=0;
	m_ActiveNodes=0;
	m_bDraw=false;
}

int Graph::AddNode(GraphNode G)
{
	for(unsigned int i=0;i<m_Nodes.size();++i)
	{
		D3DXVECTOR2 diff = G.GetPos()-m_Nodes[i].GetPos();
		if(diff.x<0.001&&diff.y<0.001&&diff.x>-0.001&&diff.y>-0.001)
		//if(diff.x==0&&diff.y==0)
		{
			G=m_Nodes[i];
		}
	}
	if(!G.GetActive())
	{
		m_ActiveNodes++;
	}
	G.Activate();
	if(G.GetIndex()<0)
	{
		std::list<GraphEdge> l;
		G.SetIndex(m_NextIndex);
		m_Nodes.push_back(G);
		m_Edges.push_back(l);
		m_NextIndex++;

#ifdef _DEBUG
		LPD3DXMESH mesh;
		D3DXCreateBox(TheD3DApp::Instance()->GetD3DDev(),1,1,1,&mesh,0);

#ifdef VORONOI_DEBUG
		
		wchar_t buf[100];
		wsprintf(buf,L"%d",G.GetIndex());

		HRESULT hr;
		HDC hdx;
		HFONT font;
		hdx=CreateCompatibleDC(NULL);

		font=CreateFont(80,         //Height
			0,          //Width
			0,          //Escapement
			0,          //Orientation
			FW_NORMAL,  //Weight
			false,      //Italic
			false,      //Underline
			false,      //Strikeout
			DEFAULT_CHARSET,//Charset 
			OUT_DEFAULT_PRECIS,  //Output Precision
			CLIP_DEFAULT_PRECIS, //Clipping Precision
			DEFAULT_QUALITY,     //Quality
			DEFAULT_PITCH|FF_DONTCARE, //Pitch and Family
			L"Arial");

		SelectObject(hdx, font);
		D3DXCreateText(TheD3DApp::Instance()->GetD3DDev(),hdx,buf,10,0.1,&mesh,0,0);
		
#endif
		GameObject* go = new GameObject(mesh);

#ifdef VORONOI_DEBUG
		go->SetScale(D3DXVECTOR3(10,10,10));
#endif
		go->SetPos(D3DXVECTOR3(G.GetPos().x,0,G.GetPos().y));
		m_NodeGOs.push_back(go);
		go->SetDraw(false);
		MainState::Instance()->addGameObject(go);

#endif	
	}
	return G.GetIndex();

}
void Graph::AddEdge(GraphEdge E)
{
	if(E.GetTo()==E.GetFrom())
	{
		return;
	}
	if(!IsEdgePresent(E.GetFrom(),E.GetTo()))
	{

		if((E.GetFrom()<m_Nodes.size() && E.GetFrom()>-1)&&(E.GetTo()<m_Nodes.size() && E.GetTo()>-1))
		{
			if(m_Nodes[E.GetFrom()].GetActive() && m_Nodes[E.GetTo()].GetActive())
			{
				m_Edges[E.GetFrom()].push_back(E);

				if(!IsEdgePresent(E.GetTo(),E.GetFrom()))
				{
					m_Edges[E.GetTo()].push_back(GraphEdge(E.GetTo(),E.GetFrom(),E.GetCost()));
				}
			}

		}
	}
	else
	{
		GetEdge(E.GetFrom(),E.GetTo()).SetCost(E.GetCost());
	}
}

void Graph::RemoveNode(int i)
{
	m_Nodes[i].Deactivate();
	m_ActiveNodes--;
}

GraphNode* Graph::GetNode(int i)
{
	return &m_Nodes[i];
}
GraphEdge Graph::GetEdge(int from, int to)
{
	//add

	GraphEdge res;

	for(std::list<GraphEdge>::iterator it = m_Edges[from].begin();it!=m_Edges[from].end();++it)
	{
		if((*it).GetFrom()==from && (*it).GetTo()==to)
		{
			res = (*it);
		}
	}

	return res;
}

std::list<GraphEdge> Graph::GetEdgeList(int i)
{
	return m_Edges[i];
}

int Graph::GetNumNodes()
{
	return m_Nodes.size();
}
int Graph::GetNumActiveNodes()
{
	return m_ActiveNodes;
}

int Graph::GetNumEdges()
{
	int res = 0;
	for(unsigned int i=0;i<m_Edges.size();++i)
	{
		res += m_Edges[i].size();
	}
	return res;
}

void Graph::Clear()
{
	m_Nodes.clear();
	m_Edges.clear();
	m_NextIndex=0;
	m_ActiveNodes=0;
}

bool Graph::IsEmpty()
{
	return m_Nodes.empty();
}
bool Graph::IsEdgePresent(int from, int to)
{

	for(std::list<GraphEdge>::iterator it = m_Edges[from].begin();it!=m_Edges[from].end();++it)
	{
		if((*it).GetFrom()==from && (*it).GetTo()==to)
		{
			return true;
		}
	}

	return false;

}

int Graph::GetNodeID(D3DXVECTOR2 d)
{
	for (unsigned int i=0;i<m_Nodes.size();++i)
	{
		if(m_Nodes[i].GetPos()==d)
		{
			return i;
		}
	}
	return -1;
}

void Graph::Render()
{
	for (unsigned int i=0;i<m_NodeGOs.size();++i)
	{
		m_NodeGOs[i]->SetDraw(m_bDraw);
	}
	if(m_bDraw)
	{
		D3DXMATRIX mv,mp,mvp;
		TheD3DApp::Instance()->GetD3DDev()->GetTransform(D3DTS_VIEW,&mv);
		TheD3DApp::Instance()->GetD3DDev()->GetTransform(D3DTS_PROJECTION,&mp);
		mvp= mv*mp;

		LPD3DXLINE l;
		D3DXCreateLine(TheD3DApp::Instance()->GetD3DDev(),&l);
		l->Begin();

		for (unsigned int i=0;i<m_Nodes.size();++i)
		{

			for(std::list<GraphEdge>::iterator it = m_Edges[i].begin();it!=m_Edges[i].end();++it)
			{

				D3DXVECTOR2 from = GetNode(it->GetFrom())->GetPos();
				D3DXVECTOR2 to = GetNode(it->GetTo())->GetPos();


				D3DXVECTOR3 points[2];
				points[0] = D3DXVECTOR3(from.x,0,from.y);
				points[1] = D3DXVECTOR3(to.x,0,to.y);


				l->DrawTransform(points,2,&mvp,D3DCOLOR_RGBA(255,255,0,255));

			}
		}

		l->End();	

	}
}